﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.IO;
using DirectShowLib;
using DirectShowLib.DES;
using Lipesin.Common;

namespace Lipesin
{
	class Program
	{
		private class Rename
		{
			public string Path { get; set; }
			public string OldName { get; set; }
			public string NewName { get; set; }
		}
		private static List<Rename> _renames = new List<Rename>();
		static void Main(string[] args)
		{
			Console.WriteLine("Конвертор имён файлов фото и видеокамер (от 19.02.2014).");
			Console.WriteLine("IMG_0001.JPG = > yyMMdd HHmmss.jpg  - фото Canon (дата и время)");
			Console.WriteLine("IMG_0001.CR2 = > yyMMdd HHmmss.cr2  - RAW Canon");
			Console.WriteLine("GOPR0014.JPG = > yyMMdd HHmmss.cr2  - фото GoPro");
			Console.WriteLine("MVI_0001.MOV = > yyMMdd HHmm 00.mov - видео Canon (в конце длинна в минутах)");
			Console.WriteLine("MVI_0010.AVI = > yyMMdd HHmm 00.avi - видео");
			Console.WriteLine("VID_0005.AVI = > yyMMdd HHmm 00.avi - видео");
			Console.WriteLine("GOPR0012.MP4 = > yyMMdd HHmm 00.mp4 - видео GoPro");
			Console.WriteLine("GP010012.MP4 = > yyMMdd HHmm+00.mp4 - продолжение видео GoPro");
			Console.WriteLine();

			Console.Title = Directory.GetCurrentDirectory();
			string basePath = Directory.GetCurrentDirectory();
			DirectoryInfo dir = new DirectoryInfo(basePath);

			System.Diagnostics.Stopwatch sw = new System.Diagnostics.Stopwatch();
			sw.Restart();

			//Console.ReadKey();//debug
			CreateRenames(dir);
			if (_renames.Count == 0)
			{
				Console.WriteLine(@"Не обнаружено файлов для переименовки.");
				Console.WriteLine("Нажмите любую клавишу для выхода.");
				Console.ReadKey();
				return;
			}
			Console.WriteLine();
			Console.WriteLine(@"Переименовать эти файлы? (y/n) (просканировано за {0})".F(sw.Elapsed));
			ConsoleKeyInfo key = Console.ReadKey();
			if (key.Key != ConsoleKey.Y) return;
			Console.WriteLine();
			sw.Restart();
			foreach (Rename r in _renames)
			{
				string opath = Path.Combine(r.Path, r.OldName);
				string npath = null;
				int count = 0;
				do
				{
					npath = Path.Combine(r.Path, "{0}{1}{2}"
						.F(Path.GetFileNameWithoutExtension(r.NewName), count > 0 ? "_" + count.ToString() : "", Path.GetExtension(r.NewName)));
					count++;
				} while (File.Exists(npath));
				if (count == 2)
				{//суффикс _0 для первого файла, если их больше одного в секунду
					string pold = Path.Combine(r.Path, r.NewName);
					string pnew = Path.Combine(r.Path, "{0}{1}{2}".F(Path.GetFileNameWithoutExtension(r.NewName), "_0", Path.GetExtension(r.NewName)));
					File.Move(pold, pnew);
				}
				File.Move(opath, npath);
				Console.Write('.');
			}
			Console.WriteLine();
			Console.WriteLine(@"Переименовано файлов {0} за {1}.".F(_renames.Count, sw.Elapsed));
			Console.WriteLine("Нажмите любую клавишу для выхода.");
			Console.ReadKey();

		}
		private static void CreateRenames(DirectoryInfo dir)
		{
			List<Rename> renames = new List<Rename>();
			foreach (FileInfo file in dir.GetFiles())
			{
				Rename rename = CreateRename(file);
				if (rename != null) renames.Add(rename);
			}
			if (renames.Count > 0)
			{
				Console.WriteLine();
				Console.WriteLine("{0}; Файлов: {1}".F(dir.FullName, renames.Count));
				_renames.AddRange(renames);
				if (Console.BufferHeight < _renames.Count + 200) Console.BufferHeight = _renames.Count + 200;
				foreach (Rename r in renames) Console.WriteLine("{0} => {1}".F(r.OldName, r.NewName));
			}
			foreach (DirectoryInfo subdir in dir.GetDirectories())
				CreateRenames(subdir);
		}
		//MVI_0032.MOV
		//IMG_0001.JPG
		//GOPR0013.MP4
		//GP010013.MP4
		private static Rename CreateRename(FileInfo file)
		{
			Rename rename = new Rename();
			rename.Path = file.DirectoryName;
			rename.OldName = file.Name.ToLower();
			rename.NewName = null;
			string extension = file.Extension.ToLower();

			string photoMask = @"^(img_\d{4}\.(jpg|cr2))|(gopr\d{4}\.jpg)$";
			System.Text.RegularExpressions.Regex photoValidator = new System.Text.RegularExpressions.Regex(photoMask);
			string videoMask = @"^(mvi_\d{4}\.(mov|avi))|(vid_\d{4}\.avi)|((gopr\d{4}|gp\d{6}).*\.mp4)$";
			System.Text.RegularExpressions.Regex videoValidator = new System.Text.RegularExpressions.Regex(videoMask);
			//bool test = photoValidator.IsMatch("img_0002.jpg");

			if (photoValidator.IsMatch(rename.OldName))
			{//фотоблок
				rename.NewName = string.Format("{0:yyMMdd HHmmss}", file.LastWriteTime);
				rename.NewName += extension;
			}
			else if (videoValidator.IsMatch(rename.OldName))
			{//видеоблок
				TimeSpan vlen = new TimeSpan();
				try
				{
					IMediaDet mediaDet = (IMediaDet)new MediaDet();
					DsError.ThrowExceptionForHR(mediaDet.put_Filename(file.FullName));
					// find the video stream in the file
					Guid type = Guid.Empty;
					for (int index = 0; index < 1000 && type != MediaType.Video; index++)
					{
						mediaDet.put_CurrentStream(index);
						mediaDet.get_StreamType(out type);
					}
					double mediaLength = 0;
					mediaDet.get_StreamLength(out mediaLength);
					vlen = new TimeSpan(0, 0, Convert.ToInt32(mediaLength));
				}
				catch (Exception ex)
				{
					string exception = ex.ToString();
				}

				rename.NewName = string.Format(@"{0:yyMMdd HHmm}{1}{2:00}", file.LastWriteTime.Subtract(vlen), rename.OldName.StartsWith("gp") ? "+" : " ", vlen.TotalMinutes);
				rename.NewName += extension;
			}
			if (rename.NewName == null) return null;
			return rename;
		}
	}
}
